package com.dq.context.schedule;

import com.dq.context.Constant;
import com.dq.domain.goods.stock.StockChangeRecord;
import com.dq.domain.service.ServiceProject;
import com.dq.domain.statistics.*;
import com.dq.domain.subscribe.Subscribe;
import com.dq.domain.sys.role.SysRoleSection;
import com.dq.domain.sys.role.SysUserRole;
import com.dq.domain.sys.section.SysSection;
import com.dq.domain.sys.user.Account;
import com.dq.domain.sys.user.center.UserAccountStaffUser;
import com.dq.domain.sys.user.user.BossUser;
import com.dq.exception.customException.AdminException;

import com.dq.domain.goods.Goods;
import com.dq.domain.goods.Product;
import com.dq.domain.message.oneself.Message;
import com.dq.domain.message.oneself.NoticeMessage;
import com.dq.domain.message.oneself.SubscribeMessage;
import com.dq.domain.orders.UserOrder;
import com.dq.domain.orders.info.OrderInfo;
import com.dq.domain.org.Org;
import com.dq.domain.record.*;
import com.dq.domain.reward.Reward;
import com.dq.domain.sys.user.user.StaffUser;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.domain.sys.user.user.WxUser;
import com.dq.dto.OrgStatisticeDto;
import com.dq.service.AllService;
import com.dq.utils.DateUtils;
import com.dq.utils.TimeUtil;
import lombok.extern.java.Log;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author ----
 * @date 2019/11/29 0029 17:13:25
 */
@Log
@Component
public class TimeTask extends AllService{
    @Value("${score_sum}")
    private Long scoreSum;


    /**
     * 每天晚上2点统计前一天的销售额
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void generateSalePrice(){
        Long lastZero = TimeUtil.getLastDayZeroTimestamp();
        List<Statistics> statisticsList = new ArrayList<>();
        List<Org> orgs = orgRepository.findAll();
        orgs.forEach(org -> {
            BigDecimal sumPrice = userOrderRepository.countSalePrice(org, UserOrder.UserOrderStatus.alreadyCheckOut,lastZero,System.currentTimeMillis());
            Statistics saleStatistics = new Statistics(lastZero,0L,org, Statistics.StatisticsType.salePrice,sumPrice);
            statisticsList.add(saleStatistics);
        });
        if(statisticsList.size()>0){
            statisticsRepository.saveAll(statisticsList);
        }
    }
    /**
     * 统计消费排行榜
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void generateSaleStatustics(){
        List<WxUser> wxUsers = wxUserRepository.findByDeletedFalse();
        List<SaleStatistics> list = new ArrayList<>();
        Long begin = TimeUtil.getLastDayZeroTimestamp();
        Long end = TimeUtil.getLastDayEndTimeStamp();
        for(WxUser wxUser : wxUsers){
           List<Account> accounts = accountRepository.findByDeletedFalseAndUserAndCreateTimeGreaterThanAndCreateTimeLessThanAndChangeType(wxUser,begin,end, Account.ChangeType.add);
           BigDecimal topPrice = BigDecimal.ZERO;
           for(Account account : accounts){
               if(account.getPrice() != null) {
                   topPrice = topPrice.add(account.getPrice());
               }
           }
           List<Account> accountsexpendPrice = accountRepository.findByDeletedFalseAndUserAndCreateTimeGreaterThanAndCreateTimeLessThanAndChangeType(wxUser,begin,end, Account.ChangeType.less);
           BigDecimal expendPrice = BigDecimal.ZERO;
           for(Account account : accountsexpendPrice){
               if(account.getPrice() != null) {
                   expendPrice = expendPrice.add(account.getPrice());
               }
           }

            SaleStatistics saleStatistics = new SaleStatistics();
            saleStatistics.setCreateTime(begin);
            saleStatistics.setTopPrice(topPrice);
            saleStatistics.setExpendPrice(expendPrice);
            saleStatistics.setWxUser(wxUser);
            SysSection section = wxUser.getSection();
            if(section instanceof Org){
                saleStatistics.setOrg((Org) wxUser.getSection());
            }

            list.add(saleStatistics);
        }
        if(list.size() > 0){
            saleStatisticsRepository.saveAll(list);
        }
    }

    /**
     * 业绩排行榜统计
     * 0 0 2 * * ?
     * 0/20 * * * * ?
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void generateAchievementStatustics(){
        List<BossUser> bossUsers = bossUserRepository.findByDeletedFalse();
        Long begin = TimeUtil.getLastDayZeroTimestamp();
        Long end = TimeUtil.getLastDayEndTimeStamp();
        List<AchievementStatistics> list = new ArrayList<>();
        for(BossUser bossUser : bossUsers){
            AchievementStatistics achievementStatistics = new AchievementStatistics();
            achievementStatistics.setCreateTime(begin);

            BigDecimal rechargePrice = BigDecimal.ZERO;
            BigDecimal consumePrice = BigDecimal.ZERO;
//            List<Account> accounts = accountRepository.findByDeletedFalseAndStaffUserAndCreateTimeGreaterThanAndCreateTimeLessThanAndAccountChangeType(bossUser,begin,end,Account.AccountChangeType.recharge);
            List<UserAccountStaffUser> userAccountStaffUserList = userAccountStaffUserRepository.findByDeletedFalseAndStaffUserAndCreateTimeGreaterThanAndCreateTimeLessThanAndAccountAccountChangeType(bossUser,begin,end,Account.AccountChangeType.recharge);
            List<Account> accounts = new ArrayList<>();
            for(UserAccountStaffUser userAccountStaffUser : userAccountStaffUserList){
                if(userAccountStaffUser.getAccount() != null){
                    accounts.add(userAccountStaffUser.getAccount());
                }
            }
            for(Account account : accounts){
                rechargePrice = rechargePrice.add(account.getPrice());
            }
            accounts = accountRepository.findByDeletedFalseAndStaffUserAndCreateTimeGreaterThanAndCreateTimeLessThanAndAccountChangeType(bossUser,begin,end,Account.AccountChangeType.deduct);
            for(Account account : accounts){
                consumePrice = consumePrice.add(account.getPrice());
            }
            achievementStatistics.setRechargePrice(rechargePrice);
            achievementStatistics.setConsumePrice(consumePrice);
            achievementStatistics.setSalePrice(rechargePrice.add(consumePrice));
            SysSection section = bossUser.getSection();
            if(section instanceof Org){
                achievementStatistics.setOrg((Org) bossUser.getSection());
            }

            try {
                List<Long> ids = new ArrayList<>();
                if(StringUtils.isNotBlank(section.getAncestors())) {
                    String[] split = section.getAncestors().split(",");
                    for (String s : split) {
                        ids.add(Long.parseLong(s));
                    }
                };
                if(ids.size() > 0) {
                    List<SysRoleSection> roleSections = sysRoleSectionRepository.findByDeletedIsFalseAndSectionIdInOrderBySectionIdDesc(ids);
                    for (SysRoleSection roleSection : roleSections) {
                        if(roleSection.getSysRole() != null && roleSection.getSysRole().getCode().equals(Constant.ROLE_CODE_LIST.get(2))) {
                            achievementStatistics.setDepartment(roleSection.getSection());
                            break;
                        }
                    }
                    for (SysRoleSection roleSection : roleSections) {
                        if(roleSection.getSysRole() != null && roleSection.getSysRole().getCode().equals(Constant.ROLE_CODE_LIST.get(1))) {
                            achievementStatistics.setProvincialSection(roleSection.getSection());
                            break;
                        }
                    }
                    if(achievementStatistics.getDepartment() == null || achievementStatistics.getProvincialSection() == null) {
                        List<SysSection> sysSections = sysSectionRepository.findByDeletedIsFalseAndIdInOrderByIdDesc(ids);
                        boolean is = false;
                        boolean isP = false;
                        for (SysSection sysSection : sysSections) {
                            List<SysUserRole> userRoles = sysUserRoleRepository.findByDeletedIsFalseAndSysUserSectionAndSysRoleDeletedFalse(sysSection);
                            for (SysUserRole userRole : userRoles) {
                                if(is && isP) {
                                    break;
                                }
                                if(userRole.getSysRole() != null && userRole.getSysRole().getCode().equals(Constant.ROLE_CODE_LIST.get(2))) {
                                    achievementStatistics.setDepartment(userRole.getSysUser().getSection());
                                    is = true;
//                                    continue;
                                }
                                if(userRole.getSysRole() != null && userRole.getSysRole().getCode().equals(Constant.ROLE_CODE_LIST.get(1))) {
                                    achievementStatistics.setProvincialSection(userRole.getSysUser().getSection());
                                    isP = true;
//                                    continue;
                                }
                            }
                            if(is && isP) {
                                break;
                            }
                        }

                    }
                }


                achievementStatistics.setSubscribeNum(subscribeRepository.countByDeletedFalseAndSubscribeStatusAndTechnicianUserAndCreateTimeGreaterThanAndCreateTimeLessThan(Subscribe.SubscribeStatus.serviced, bossUser, begin, end)+subscribeRepository.countByDeletedFalseAndSubscribeStatusAndTechnicianUserAndCreateTimeGreaterThanAndCreateTimeLessThan(Subscribe.SubscribeStatus.cancel, bossUser, begin, end));
                achievementStatistics.setSubscribeFinishNum(subscribeRepository.countByDeletedFalseAndSubscribeStatusAndTechnicianUserAndCreateTimeGreaterThanAndCreateTimeLessThan(Subscribe.SubscribeStatus.serviced, bossUser, begin, end));
                achievementStatistics.setWxuserNum(accountRepository.countByDeletedFalseAndCreateTimeGreaterThanAndCreateTimeLessThanAndStaffUserGroupByUserId(false, begin, end, bossUser.getId()));
            }catch (Exception e) {
                e.printStackTrace();
            }


            achievementStatistics.setStaffUser(bossUser);
            list.add(achievementStatistics);
        }
        if(list.size() > 0 ){
            achievementStatisticsRepository.saveAll(list);
            System.out.println("----------------");
        }
    }
    /**
     * 每天晚上2点统计前一天的预约数
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void generateSubscribeStatustics(){
        List<BossUser> bossUsers = bossUserRepository.findByDeletedFalse();
        List<SubscribeStatistics> subscribeStatistics = new ArrayList<>();
        Long lastZero = TimeUtil.getLastDayZeroTimestamp();
        bossUsers.forEach(bossUser -> {
            SubscribeStatistics vo = new SubscribeStatistics();
            List<Subscribe> subscribes = subscribeRepository.findByTechnicianUserAndDeletedFalseAndSubscribeStatusAndBeginTimeGreaterThanAndEndTimeLessThan(bossUser,Subscribe.SubscribeStatus.serviced,lastZero,System.currentTimeMillis());
            vo.setStaffUser(bossUser);
            vo.setSubscribeNum(Long.parseLong(String.valueOf(subscribes.size())));
            subscribeStatistics.add(vo);
        });
        if(subscribeStatistics.size() > 0){
            subscribeStatisticsRepository.saveAll(subscribeStatistics);
        }
    }

    /**
     * 每天晚上2点统计项目统计
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void generateServiceProjectStatustics(){
        List<ServiceProject> serviceProjects = serviceProjectRepository.findByDeletedFalse();
        List<SysSection> sysSections = sysSectionRepository.findByDeletedFalse();
        List<ServiceProjectStatistics> list = new ArrayList<>();
        Long begin = TimeUtil.getLastDayZeroTimestamp();
        Long end = TimeUtil.getLastDayEndTimeStamp();
        for(ServiceProject serviceProject : serviceProjects){

            BigDecimal rechargePrice = BigDecimal.ZERO;
            BigDecimal consumePrice = BigDecimal.ZERO;
            for(SysSection section:sysSections){
                ServiceProjectStatistics serviceProjectStatistics = new ServiceProjectStatistics();
                List<Account> accounts = accountRepository.findByDeletedFalseAndSysDeptAndCreateTimeGreaterThanAndCreateTimeLessThanAndAccountChangeTypeAndServiceProject(section,begin,end,Account.AccountChangeType.recharge,serviceProject);
                for(Account account : accounts){
                    rechargePrice = rechargePrice.add(account.getPrice());
                }
                accounts = accountRepository.findByDeletedFalseAndSysDeptAndCreateTimeGreaterThanAndCreateTimeLessThanAndAccountChangeTypeAndServiceProject(section,begin,end,Account.AccountChangeType.deduct,serviceProject);
                for(Account account : accounts){
                    consumePrice = consumePrice.add(account.getPrice());
                }
                serviceProjectStatistics.setPrice(rechargePrice.add(consumePrice));
                serviceProjectStatistics.setConsumePrice(consumePrice);
                serviceProjectStatistics.setRechargePrice(rechargePrice);
                serviceProjectStatistics.setOrg(section);
                serviceProjectStatistics.setServiceProject(serviceProject);
                serviceProjectStatistics.setCreateTime(begin);
                if(section instanceof Org){
                    serviceProjectStatistics.setSubscribeNum(subscribeRepository.countByDeletedFalseAndSubscribeStatusAndServiceProjectAndSysDeptAndCreateTimeGreaterThanAndCreateTimeLessThan(Subscribe.SubscribeStatus.serviced,serviceProject, (Org) sysSections,begin,end));
                }
                list.add(serviceProjectStatistics);
            }
        }
        if(list.size() > 0 ){
            serviceProjectStatisticsRepository.saveAll(list);
        }
    }


    /**
     * 顾客生日提醒
     */
    @Scheduled(cron = "0 0 3 * * ? ")
    public void wxUserBirthdayRemind(){
        List<WxUser> wxUsers = wxUserRepository.findByDeletedFalseAndStatus(SysUser.Status.on);
        List<Long> longs = new ArrayList<>();
        wxUsers.forEach(wxUser -> {
            Long now = TimeUtil.getTime(TimeUtil.getString(DateTime.now(),TimeUtil.YYYY_MM_DD));
            if(wxUser.getBrithday() != null){
                Long brithday = TimeUtil.getTime(TimeUtil.dayAddFMT_6(new DateTime(wxUser.getBrithday()),-3));
                if(now < brithday){
                    longs.add(wxUser.getId());
                }
            }
        });
        //给顾客本人发生日通知消息
        NoticeMessage noticeMessage = new NoticeMessage();
        noticeMessage.setUserType(SubscribeMessage.UserType.client);
        noticeMessageService.saveList(noticeMessage, longs, Message.MessageType.wxSystem);
        /**
         * 给技师 门店发
         */
        //todo 删除staffuser字段 待改
        /*List<StaffUser> staffUsers = staffUserRepository.findByDeletedFalseAndStatusAndStaffUserStatus(SysUser.Status.on, StaffUser.StaffUserStatus.on);
        List<Long> longList = new ArrayList<>();
        staffUsers.forEach(staffUser -> {
            Long now = TimeUtil.getTime(TimeUtil.getString(DateTime.now(),TimeUtil.YYYY_MM_DD));
            if(staffUser.getBrithday() != null){
                Long brithday = TimeUtil.getTime(TimeUtil.dayAddFMT_6(new DateTime(staffUser.getBrithday()),-3));
                if(now < brithday){
                    longList.add(staffUser.getId());
                }
            }
        });*/
        noticeMessage.setUserType(SubscribeMessage.UserType.staff);
//        noticeMessageService.saveList(noticeMessage, longList, Message.MessageType.wxSystem);

    }



    @Scheduled(cron = "0/10 * * * * ?")
    public void invalidSubscribe(){
        List<Subscribe> subscribes = subscribeRepository.findByDeletedFalseAndSubscribeStatus(Subscribe.SubscribeStatus.confirmed);
        List<Subscribe> list = new ArrayList<>();
        for(Subscribe subscribe : subscribes){
            if(System.currentTimeMillis() > subscribe.getTimeoutTime()){
                subscribe.setSubscribeStatus(Subscribe.SubscribeStatus.cancel);
                list.add(subscribe);
            }
        }
        if(list.size() > 0){
            subscribeRepository.saveAll(list);
        }
    }
}
